{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Boosting Black Box Variational Inference\n",
    "## Introduction\n",
    "This tutorial demonstrates how to implement boosting black box Variational Inference [1] in Pyro. In boosting Variational Inference [2], we approximate a target distribution with an iteratively selected mixture of densities. In cases where a single denisity provided by regular Variational Inference doesn't adequately approximate a target density, boosting VI thus offers a simple way of getting more complex approximations. We show how this can be implemented as a relatively straightforward extension of Pyro's SVI.\n",
    "\n",
    "## Contents\n",
    "* [Theoretical Background](#theoretical-background)\n",
    "    - [Variational Inference](#variational-inference)\n",
    "    - [Boosting Black Box Variational Inference](#bbbvi)\n",
    "* [BBBVI in Pyro](#bbbvi-pyro)\n",
    "    - [The Model](#the-model)\n",
    "    - [The Guide](#the-guide)\n",
    "    - [The Relbo](#the-relbo)\n",
    "    - [The Approximation](#the-approximation)\n",
    "    - [The Greedy Algorithm](#the-greedy-algorithm)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Theoretical Background <a class=\"anchor\" id=\"theoretical-background\"></a>\n",
    "\n",
    "### Variational Inference <a class=\"anchor\" id=\"variational-inference\"></a>\n",
    "For an introduction to regular Variational Inference, we recommend having a look at [the tutorial on SVI in Pyro](https://pyro.ai/examples/svi_part_i.html) and this excellent review [3].\n",
    "\n",
    "Briefly, Variational Inference allows us to find approximations of probability densities which are intractable to compute analytically. For instance, one might have observed variables $\\textbf{x}$, latent variables $\\textbf{z}$ and a joint distribution $p(\\textbf{x}, \\textbf{z})$. One can then use Variational Inference to approximate $p(\\textbf{z}|\\textbf{x})$. To do so, one first chooses a set of tractable densities, a variational family, and then tries to find the element of this set which most closely approximates the target distribution $p(\\textbf{z}|\\textbf{x})$.\n",
    "This approximating density is found by maximizing the Evidence Lower BOund (ELBO):\n",
    "$$ \\mathbb{E}_q[\\log p(\\mathbf{x}, \\mathbf{z})] - \\mathbb{E}_q[\\log q(\\mathbf{z})]$$\n",
    "\n",
    "where $q(\\mathbf{z})$ is the approximating density.\n",
    "\n",
    "### Boosting Black Box Variational Inference <a class=\"anchor\" id=\"bbbvi\"></a>\n",
    "\n",
    "In boosting black box Variational inference (BBBVI), we approximate the target density with a mixture of densities from the variational family:\n",
    "$$q^t(\\mathbf{z}) = \\sum_{i=1}^t \\gamma_i s_i(\\mathbf{z})$$\n",
    "\n",
    "$$\\text{where} \\sum_{i=1}^t \\gamma_i =1$$\n",
    "\n",
    "and $s_t(\\mathbf{z})$ are elements of the variational family.\n",
    "\n",
    "The components of the approximation are selected greedily by maximising the so-called Residual ELBO (RELBO) with respect to the next component $s_{t+1}(\\mathbf{z})$:\n",
    "\n",
    "$$\\mathbb{E}_s[\\log p(\\mathbf{x},\\mathbf{z})] - \\lambda \\mathbb{E}_s[\\log s(\\mathbf{z})] - \\mathbb{E}_s[\\log q^t(\\mathbf{z})]$$\n",
    "\n",
    "Where the first two terms are the same as in the ELBO and the last term is the cross entropy between the next component $s_{t+1}(\\mathbf{z})$ and the current approximation $q^t(\\mathbf{z})$.\n",
    "\n",
    "It's called *black box* Variational Inference because this optimization does not have to be tailored to the variational family which is being used. By setting $\\lambda$ (the regularization factor of the entropy term) to 1, standard SVI methods can be used to compute $\\mathbb{E}_s[\\log p(\\mathbf{x}, \\mathbf{z})] - \\lambda \\mathbb{E}_s[\\log s(\\mathbf{z})]$. See the explanation of [the section on the implementation of the RELBO](#the-relbo) below for an explanation of how we compute the term  $- \\mathbb{E}_s[\\log q^t(\\mathbf{z})]$. Imporantly, we do not need to make any additional assumptions about the variational family that's being used to ensure that this algorithm converges. \n",
    "\n",
    "In [1], a number of different ways of finding the mixture weights $\\gamma_t$ are suggested, ranging from fixed step sizes based on the iteration to solving the optimisation problem of finding $\\gamma_t$ that will minimise the RELBO. Here, we used the fixed step size method.\n",
    "For more details on the theory behind boosting black box variational inference, please refer to [1]."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## BBBVI in Pyro <a class=\"anchor\" id=\"bbbvi-pyro\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To implement boosting black box variational inference in Pyro, we need to consider the following points:\n",
    "1. The approximation components $s_{t}(\\mathbf{z})$ (guides).\n",
    "2. The RELBO.\n",
    "3. The approximation itself $q^t(\\mathbf{z})$.\n",
    "4. Using Pyro's SVI to find new components of the approximation.\n",
    "\n",
    "We will illustrate these points by looking at simple example: approximating a bimodal posterior.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from collections import defaultdict\n",
    "from functools import partial\n",
    "\n",
    "import numpy as np\n",
    "import pyro\n",
    "import pyro.distributions as dist\n",
    "import scipy.stats\n",
    "import torch\n",
    "import torch.distributions.constraints as constraints\n",
    "from matplotlib import pyplot\n",
    "from pyro.infer import SVI, Trace_ELBO\n",
    "from pyro.optim import Adam\n",
    "from pyro.poutine import block, replay, trace\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Model <a class=\"anchor\" id=\"the-model\"></a>\n",
    "\n",
    "Boosting BBVI is particularly useful when we want to approximate multimodal distributions. In this tutorial, we'll thus consider the following model:\n",
    " \n",
    " $$\\mathbf{z} \\sim \\mathcal{N}(0,5)$$\n",
    " $$\\mathbf{x} \\sim \\mathcal{N}(\\mathbf{z}^2, 0.1)$$\n",
    " \n",
    "Given the set of iid. observations $\\text{data} ~ \\mathcal{N}(4, 0.1)$, we thus expect $p(\\mathbf{z}|\\mathbf{x})$ to be a bimodal distributions with modes around $-2$ and $2$.\n",
    " \n",
    "In Pyro, this model takes the following shape:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def model(data):\n",
    "    prior_loc = torch.tensor([0.])\n",
    "    prior_scale = torch.tensor([5.])\n",
    "    z = pyro.sample('z', dist.Normal(prior_loc, prior_scale))\n",
    "    scale = torch.tensor([0.1])\n",
    "\n",
    "    with pyro.plate('data', len(data)):\n",
    "        pyro.sample('x', dist.Normal(z*z, scale), obs=data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Guide <a class=\"anchor\" id=\"the-guide\"></a>\n",
    "\n",
    "Next, we specify the guide which in our case will make up the components of our mixture. Recall that in Pyro the guide needs to take the same arguments as the model which is why our guide function also takes the data as an input. \n",
    "\n",
    "We also need to make sure that every `pyro.sample()` statement from the model has a matching `pyro.sample()` statement in the guide. In our case, we include `z` in both the model and the guide.\n",
    "\n",
    "In contrast to regular SVI, our guide takes an additional argument: `index`. Having this argument allows us to easily create new guides in each iteration of the greedy algorithm. Specifically, we make use of `partial()` from the [functools library](https://docs.python.org/3.7/library/functools.html) to create guides which only take `data` as an argument. The statement `partial(guide, index=t)` creates a guide that will take only `data` as an input and which has trainable parameters `scale_t` and `loc_t`.\n",
    "\n",
    "Choosing our variational distribution to be a Normal distribution parameterized by $loc_t$ and $scale_t$ we get the following guide:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def guide(data, index):\n",
    "    scale_q = pyro.param('scale_{}'.format(index), torch.tensor([1.0]), constraints.positive)\n",
    "    loc_q = pyro.param('loc_{}'.format(index), torch.tensor([0.0]))\n",
    "    pyro.sample(\"z\", dist.Normal(loc_q, scale_q))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The RELBO <a class=\"anchor\" id=\"the-relbo\"></a>\n",
    "\n",
    "We implement the RELBO as a function which can be passed to Pyro's SVI class in place of ELBO to find the approximation components $s_t(z)$. Recall that the RELBO has the following form:\n",
    "$$\\mathbb{E}_s[\\log p(\\mathbf{x},\\mathbf{z})] - \\lambda \\mathbb{E}_s[\\log s(\\mathbf{z})] - \\mathbb{E}_s[\\log q^t(\\mathbf{z})]$$\n",
    "\n",
    "Conveniently, this is very similar to the regular ELBO which allows us to reuse Pyro's existing ELBO. Specifically, we compute \n",
    "$$\\mathbb{E}_s[\\log p(x,z)] - \\lambda \\mathbb{E}_s[\\log s]$$\n",
    "\n",
    "using Pyro's `Trace_ELBO` and then compute \n",
    "$$ - \\mathbb{E}_s[\\log q^t]$$\n",
    "\n",
    "using Poutine. For more information on how this works, we recommend going through the Pyro tutorials [on Poutine](https://pyro.ai/examples/effect_handlers.html) and [custom SVI objectives](https://pyro.ai/examples/custom_objectives.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def relbo(model, guide, *args, **kwargs):\n",
    "    approximation = kwargs.pop('approximation')\n",
    "\n",
    "    # We first compute the elbo, but record a guide trace for use below.\n",
    "    traced_guide = trace(guide)\n",
    "    elbo = pyro.infer.Trace_ELBO(max_plate_nesting=1)\n",
    "    loss_fn = elbo.differentiable_loss(model, traced_guide, *args, **kwargs)\n",
    "\n",
    "    # We do not want to update parameters of previously fitted components\n",
    "    # and thus block all parameters in the approximation apart from z.\n",
    "    guide_trace = traced_guide.trace\n",
    "    replayed_approximation = trace(replay(block(approximation, expose=['z']), guide_trace))\n",
    "    approximation_trace = replayed_approximation.get_trace(*args, **kwargs)\n",
    "\n",
    "    relbo = -loss_fn - approximation_trace.log_prob_sum()\n",
    "    \n",
    "    # By convention, the negative (R)ELBO is returned.\n",
    "    return -relbo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Approximation <a class=\"anchor\" id=\"the-approximation\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Our implementation of the approximation $q^t(z) = \\sum_{i=1}^t \\gamma_i s_i(z)$ consists of a list of components, i.e. the guides from the greedy selection steps, and a list containing the mixture weights of the components. To sample from the approximation, we thus first sample a component according to the mixture weights. In a second step, we draw a sample from the corresponding component.\n",
    "\n",
    "Similarly as with the guide, we use `partial(approximation, components=components, weights=weights)` to get an approximation function which has the same signature as the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def approximation(data, components, weights):\n",
    "    assignment = pyro.sample('assignment', dist.Categorical(weights))\n",
    "    result = components[assignment](data)\n",
    "    return result        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Greedy Algorithm <a class=\"anchor\" id=\"the-greedy-algorithm\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now have all the necessary parts to implement the greedy algorithm. First, we initialize the approximation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_approximation = partial(guide, index=0)\n",
    "components = [initial_approximation]\n",
    "weights = torch.tensor([1.])\n",
    "wrapped_approximation = partial(approximation, components=components, weights=weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we iteratively find the $T$ components of the approximation by maximizing the RELBO at every step:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameters of component 1:\n",
      "loc = -2.0068717002868652\n",
      "scale = 0.01799079217016697\n",
      ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameters of component 2:\n",
      "loc = 2.0046799182891846\n",
      "scale = 0.06008879840373993\n"
     ]
    }
   ],
   "source": [
    "# clear the param store in case we're in a REPL\n",
    "pyro.clear_param_store()\n",
    "\n",
    "# Sample observations from a Normal distribution with loc 4 and scale 0.1\n",
    "n = torch.distributions.Normal(torch.tensor([4.0]), torch.tensor([0.1]))\n",
    "data = n.sample((100,))\n",
    "\n",
    "#T=2\n",
    "smoke_test = ('CI' in os.environ)\n",
    "n_steps = 2 if smoke_test else 12000\n",
    "pyro.set_rng_seed(2)\n",
    "n_iterations = 2\n",
    "locs = [0]\n",
    "scales = [0]\n",
    "for t in range(1, n_iterations + 1):\n",
    "\n",
    "    # Create guide that only takes data as argument\n",
    "    wrapped_guide = partial(guide, index=t)\n",
    "    losses = []\n",
    "\n",
    "    adam_params = {\"lr\": 0.01, \"betas\": (0.90, 0.999)}\n",
    "    optimizer = Adam(adam_params)\n",
    "\n",
    "    # Pass our custom RELBO to SVI as the loss function.\n",
    "    svi = SVI(model, wrapped_guide, optimizer, loss=relbo)\n",
    "    for step in range(n_steps):\n",
    "        # Pass the existing approximation to SVI.\n",
    "        loss = svi.step(data, approximation=wrapped_approximation)\n",
    "        losses.append(loss)\n",
    "\n",
    "        if step % 100 == 0:\n",
    "            print('.', end=' ')\n",
    "\n",
    "    # Update the list of approximation components.\n",
    "    components.append(wrapped_guide)\n",
    "\n",
    "    # Set new mixture weight.\n",
    "    new_weight = 2 / (t + 1)\n",
    "\n",
    "    # In this specific case, we set the mixture weight of the second component to 0.5.\n",
    "    if t == 2:\n",
    "        new_weight = 0.5\n",
    "    weights = weights * (1-new_weight)\n",
    "    weights = torch.cat((weights, torch.tensor([new_weight])))\n",
    "\n",
    "    # Update the approximation\n",
    "    wrapped_approximation = partial(approximation, components=components, weights=weights)\n",
    "\n",
    "    print('Parameters of component {}:'.format(t))\n",
    "    scale = pyro.param(\"scale_{}\".format(t)).item()\n",
    "    scales.append(scale)\n",
    "    loc = pyro.param(\"loc_{}\".format(t)).item()\n",
    "    locs.append(loc)\n",
    "    print('loc = {}'.format(loc))\n",
    "    print('scale = {}'.format(scale))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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x0T//v1FQECACA8PF5mZmZrW7LbndKSoqEikpaWJsLAw4evrKzp16qRp1242m0X37t3FzTffLC5duqR57quvvioAiLVr12quVbXVfJMmTeyu27dvX3H77bfbHa/acv369eti+vTpIjIyUvj7+4tevXqJ/Px80bdvX9G3b1/Nczds2CA6dOggDAaDJo6qreaFqGhbPm3aNBEVFSV8fHxE27Ztxfz584XFYtGMAyAmTZrkME7b1ujO1PT+Onvd1VFievfdd0Xbtm2F0WgUcXFxDveM2rNnj0hOThaBgYEiICBA9OvXT2zfvl0z5oUXXhA9evQQISEhwt/fX9x2223ixRdf1OxRZTabxeTJk0Xz5s2FJEl2beffeustER8fL/z9/UVQUJDo1KmTeOqpp0RBQYFLr9HR+3ns2DExaNAgERISIvz8/ESPHj3Exx9/rBmjtJq33XerJq5+7xW9evUSAMTYsWOdnvO3vv6qMjMz1S0Fqt6q/twTkfeRhGgkq46JiDzo5MmTiI2Nxfz58/HEE09UO3bUqFFYv349rly5coOio4ZCkiRMmjTJbuocERF5B675IiIiIiIiugGYfBEREREREd0ATL6IiIiIiIhuAK75IiIiIiIiugFY+SIiIiIiIroBmHwRERERERHdANxkuZYsFgsKCgoQFBQESZI8HQ4REREREXmIEAK//voroqKiqt1MnslXLRUUFCA6OtrTYRARERERUQNx5swZ3HzzzU4fZ/JVS0FBQQAq3uCmTZt6OBoiIiIiIvKU4uJiREdHqzmCM0y+akmZati0aVMmX0REREREVONyJDbcICIiIiIiugGYfBEREREREd0ATL6IiIiIiIhuACZfRERERERENwCTLyIiIiIiohugQSRfOTk5MJlM8PPzQ0JCAnbt2uV07N///nfcddddaNasGZo1a4akpCS78UIIzJw5E5GRkfD390dSUhKOHDmiGfPzzz/jkUceQdOmTRESEoIxY8bgypUr9fL6iIiIiIiIPJ58rV27FhkZGcjMzMSePXvQpUsXJCcn4/z58w7Hb9myBcOHD8fmzZuRn5+P6Oho9O/fH2fPnlXHvPzyy3jttdewdOlS7Ny5E02aNEFycjKuX7+ujnnkkUdw4MABfPbZZ/j444+xbds2jB8/vt5fLxEREREReSdJCCE8GUBCQgK6d++OxYsXAwAsFguio6MxefJkPPPMMzU+X5ZlNGvWDIsXL8bIkSMhhEBUVBSmT5+OJ554AgBw+fJlhIeHY+XKlRg2bBi+//57dOjQAV999RW6desGAMjNzcWAAQPw448/IioqqsbrFhcXIzg4GJcvX+Y+X0REREREXszV3MCjla+ysjLs3r0bSUlJ6jGdToekpCTk5+e7dI6SkhKUl5cjNDQUAHDixAkUFhZqzhkcHIyEhAT1nPn5+QgJCVETLwBISkqCTqfDzp07HV6ntLQUxcXFmhsREREREZGrPJp8Xbx4EbIsIzw8XHM8PDwchYWFLp3j6aefRlRUlJpsKc+r7pyFhYVo0aKF5nGDwYDQ0FCn183KykJwcLB6i46Odik+IiIibyYsFk+HQETUYHh8zddvMW/ePKxZswb/+te/4OfnV6/XmjFjBi5fvqzezpw5U6/XIyIi+r0rKbmI+1d2wXOrk2oeTETkBQyevHhYWBj0ej2Kioo0x4uKihAREVHtcxcsWIB58+Zh06ZN6Ny5s3pceV5RUREiIyM15+zatas6pmpDD7PZjJ9//tnpdY1GI4xGo+svjoiIyMudPP0FzuqB69ddm81CRNTYebTy5evri/j4eOTl5anHLBYL8vLykJiY6PR5L7/8MubOnYvc3FzNui0AiI2NRUREhOacxcXF2Llzp3rOxMREXLp0Cbt371bHfP7557BYLEhISKirl0dEROTVZLkcAGCWPBwIEVED4dHKFwBkZGQgNTUV3bp1Q48ePZCdnY2rV68iLS0NADBy5Ei0bNkSWVlZAIC//e1vmDlzJlavXg2TyaSu0QoMDERgYCAkScLUqVPxwgsvoG3btoiNjcXzzz+PqKgoDBw4EADQvn173HfffRg3bhyWLl2K8vJypKenY9iwYS51OiQiIqKayZayin89HAcRUUPh8eRr6NChuHDhAmbOnInCwkJ07doVubm5asOM06dPQ6erLNAtWbIEZWVlGDRokOY8mZmZmDVrFgDgqaeewtWrVzF+/HhcunQJvXv3Rm5urmZd2KpVq5Ceno57770XOp0OKSkpeO211+r/BRMREXkJs1L58nAcREQNhcf3+fq94j5fRERE1dux+02M+24xDELgm1HfeTocIqJ687vY54uIiIgaL9mirPmS2HKeiAhMvoiIiKieKMkXAMhymQcjISJqGJh8ERERUb1Q1nwB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Hwa62YPCgQMHxMsvvywOHz4sTp8+Ld59910xcuRIsXDhQlfM9c9YCCF++ctfijFjxoh9+/aJQ4cOiYyMDJGRkRGMlxDSzp8/L2699VYxZ84ccf78eXHp0iXXV88Y9uG+27lzp9BoNGL79u3i22+/FUuWLBGxsbGuVWYfeugh8Zvf/MYV/+WXXwqVSiVefPFFcezYMbF69WqhVqvF3//+92C9hJD22GOPiZiYGFFRUeHWX00mkyvm+me8du1a8emnn4rTp0+L6upqsWDBAqHVasXRo0eD8RJC2lNPPSUqKirEmTNnxJdffimysrJEfHy8aGhoEEKw/w4Uq9UqxowZI55++mmPc+y//dPS0uL6vAtAlJaWitraWnHu3DkhhBAbNmwQsbGx4qOPPhLffPONuP/++0Vqaqpob2933eNf//VfxcaNG10/9/Y+HihMvgaBhx9+WADw+Nq/f78r5uzZs+Lee+8VOp1OxMfHi6eeekqYzWbX+f379wsA4syZM65jV69eFXl5eSIyMlJER0eLgoICV0JHQuTl5YnMzEzZc2fOnHH7b1BXVyd++MMfiri4OKHRaMStt94qVqxYIZqamgLY4sGjurpaGAwGERMTI7RarZg0aZL43e9+Jzo6Olwx1z9jIYRob28Xv/rVr8Tw4cOFXq8XP/7xj90SCrLbtm2b7HtGz39vYx/uv40bN4oxY8aIiIgIMWvWLPHVV1+5zs2ePVs8/PDDbvEffPCBuO2220RERIS44447xH//938HuMWDh7f+um3bNlfM9c/4iSeecP33SExMFD/60Y9ETU1N4Bs/CMyfP1+MGjVKREREiJtuuknMnz9fnDp1ynWe/XdgfPrppwKAOHHihMc59t/+cX5uvf7L+QxtNpt49tlnRWJiotBoNGLOnDkez33s2LFi9erVbsd8vY8HiiSEEAEpsREREREREYUx7vNFREREREQUAEy+iIiIiIiIAoDJFxERERERUQAw+SIiIiIiIgoAJl9EREREREQBwOSLiIiIiIgoAJh8ERERERERBQCTLyIiIiIiogBg8kVERERERBQATL6IiIiIiIgCgMkXERERERFRADD5IiIiIiIiCoD/D1kzSdGioH+6AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 1000x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the resulting approximation\n",
    "X = np.arange(-10, 10, 0.1)\n",
    "pyplot.figure(figsize=(10, 4), dpi=100).set_facecolor('white')\n",
    "total_approximation = np.zeros(X.shape)\n",
    "for i in range(1, n_iterations + 1):\n",
    "    Y = weights[i].item() * scipy.stats.norm.pdf((X - locs[i]) / scales[i])\n",
    "    pyplot.plot(X, Y)\n",
    "    total_approximation += Y\n",
    "pyplot.plot(X, total_approximation)\n",
    "pyplot.plot(data.data.numpy(), np.zeros(len(data)), 'k*')\n",
    "pyplot.title('Approximation of posterior over z')\n",
    "pyplot.ylabel('probability density')\n",
    "pyplot.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see that boosting BBVI successfully approximates the bimodal posterior distributions with modes around -2 and +2."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Complete Implementation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Putting all the components together, we then get the complete implementation of boosting black box Variational Inference:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameters of component 1:\n",
      "loc = -1.9996534585952759\n",
      "scale = 0.016739774495363235\n",
      ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameters of component 2:\n",
      "loc = 1.998241901397705\n",
      "scale = 0.01308442372828722\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA18AAAFwCAYAAABHI8GjAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOzde1xUZf4H8M+Z4X6XUBAjBi+Z5o1QkTTJYqWsdt3Q1NoV8dZFNMVutileKtw0pdK0dr30Kl1Na/NXuVRS6paopZmm6XohNRHUUkhRYM55fn8wc5jDzDAzCA4yn/frNS/hzDPnPDPMS+bL9/t8H0kIIUBERERERESNSufuCRAREREREXkCBl9ERERERETXAIMvIiIiIiKia4DBFxERERER0TXA4IuIiIiIiOgaYPBFRERERER0DTD4IiIiIiIiugYYfBEREREREV0DDL6IiIiIiIiuAQZfRESEn3/+GZIkYeXKle6eisaoUaNgMBjcPY06Xbx4EWPHjkVUVBQkScLkyZPdPaVrymAwYNSoUe6eBhHRdYHBFxGRE958801IkoTExER3T6XZKSoqwsyZM7Fnzx53T6VeXn75ZaxcuRKPP/443n33Xfz1r39195Q0Nm7ciJkzZ7p7GkREBEASQgh3T4KIqKnr27cvioqK8PPPP+Pw4cNo3769u6fUoIQQqKiogLe3N/R6/TW99nfffYdevXphxYoVVhmUqqoqKIoCX1/fazonV/Tp0wdeXl74+uuv3T0VmzIzM7F48WI01q/7iooK6HQ6eHt7N8r5iYiaE2a+iIgcKCwsxLZt27BgwQK0bNkSq1atcttcjEYjKisrG/y8kiTBz8/vmgdejnh7ezfpwAsAzpw5g7CwMHdP45oSQuDy5csAAF9f3wYLvK5cuQJFURrkXI3J8vkTEbmCwRcRkQOrVq1CixYtcN9992HIkCE2gy/zmqn58+dj4cKFiI2Nhb+/P5KTk/Hjjz9qxo4aNQpBQUE4duwYUlNTERgYiOjoaMyePVuTnbA8Z25uLtq1awdfX18cOHAAQPWH/jFjxiAyMhJ+fn7o3r073nnnHc21srOzodPpkJ+frzk+fvx4+Pj44IcfftBcy3LNl3meJ06cwP3334+goCC0adMGixcvBgDs27cPd911FwIDAxEbG4vVq1drrvHbb7/hqaeeQteuXREUFISQkBDce++96jUBYPPmzejVqxcAICMjA5IkaeZha83XpUuXMHXqVMTExMDX1xcdO3bE/PnzrTI7kiQhMzMTH330Ebp06QJfX1/ceuutyMvLs/r52eLo9d28eTMkSUJhYSE+/fRTde4///yz3XOa57Rq1Sp07NgRfn5+SEhIwNatW63Gfv/997j33nsREhKCoKAg3H333di+fbtmTFVVFWbNmoUOHTrAz88PN9xwA/r164cvvvhCff3MPy/z/CRJUh+vKApyc3Nx6623ws/PD5GRkXj00Udx/vx5zXUMBgPuv/9+fPbZZ+jZsyf8/f3x1ltvqffVzlgeO3YMQ4cORXh4OAICAtCnTx98+umnmjHm12/NmjV44YUX0KZNGwQEBKCsrMzu6+fMz75Lly4YMGCA1WMVRUGbNm0wZMiQBn3+ta1cuVLzWlve7rzzTrvPjYg8hCAiojrdcsstYsyYMUIIIbZu3SoAiJ07d2rGFBYWCgCia9euwmAwiL///e9i1qxZIjw8XLRs2VIUFxerY9PT04Wfn5/o0KGD+Otf/yoWLVok7r//fgFATJ8+3eqcnTt3Fm3bthVz584VCxcuFMePHxfl5eWiU6dOwtvbW0yZMkW8/vrr4o477hAARG5urnqOyspKER8fL2JjY0VZWZkQQoi8vDwBQMyZM8fqWitWrLCaZ+fOncVjjz0mFi9eLG6//XZ1XHR0tHj66afFG2+8IW699Vah1+vFsWPH1Md/++23ol27duK5554Tb731lpg9e7Zo06aNCA0NFadOnRJCCFFcXCxmz54tAIjx48eLd999V7z77rvi6NGj6hxiY2PVcyqKIu666y4hSZIYO3asWLRokXjggQcEADF58mTNzwSA6N69u2jdurWYM2eOyM3NFW3bthUBAQHi3Llzdf7MnXl9i4uLxbvvvisiIiJEjx491LlfvHjR7nkBiC5duoiIiAgxe/Zs8fe//13ExsYKf39/sW/fPnXcjz/+KAIDA9W5z507V8TFxQlfX1+xfft2ddzzzz8vJEkS48aNE//4xz/Eq6++KkaMGCHmzp0rhBBi27Zt4g9/+IMAoM7v3XffVR8/duxY4eXlJcaNGyeWLl0qnn32WREYGCh69eolKisr1XGxsbGiffv2okWLFuK5554TS5cuFV999ZV6X3p6ujq2uLhYREZG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6FExcOBAERAQICIjI0V2dramNbvlOW0pKSkRGRkZIiIiQvj4+IiuXbtq2rUbjUbRq1cvceONN4oLFy5oHvvaa68JAGLt2rWaa9VuNR8YGGh13eTkZHHrrbdaHa/dcv3KlSti6tSponXr1sLf31/07dtXFBQUiOTkZJGcnKx57IYNG0Tnzp2Fl5eXZh61W80LUd22fMqUKSI6Olp4e3uLDh06iHnz5glFUTTjAIgJEybYnKdla3R7HL2+9p53Xcxzeu+990SHDh2Er6+viI+Pt7ln1O7du0VqaqoICgoSAQEBYsCAAWLbtm2aMS+++KLo3bu3CAsLE/7+/uKWW24RL730kmaPKqPRKCZOnChatmwpJEmyajv/9ttvi4SEBOHv7y+Cg4NF165dxTPPPCOKioqceo62Xs+jR4+KIUOGiLCwMOHn5yd69+4tPvnkE80Yc6t5y323HHH2Z2/Wt29fAUCMHTvW7jmv9vnXlp2drW4pUPtW+31PRJ5HEqKZrDomInKjn3/+GXFxcZg3bx6eeuqpOseOGjUK69evx8WLF6/R7KipkCQJEyZMsCqdIyIiz8A1X0RERERERNcAgy8iIiIiIqJrgMEXERERERHRNcA1X0RERERERNcAM19ERERERETXAIMvIiIiIiKia4CbLNeToigoKipCcHAwJEly93SIiIiIiMhNhBD4/fffER0dXedm8gy+6qmoqAgxMTHungYRERERETURJ0+exI033mj3fgZf9RQcHAyg+gUOCQlx82yIiIiIiMhdysrKEBMTo8YI9jD4qidzqWFISAiDLyIiIiIicrgciQ03iIiIiIiIrgEGX0RERERERNcAgy8iIiIiIqJrgMEXERERERHRNcDgi4iIiIiI6Bpg8EVERERERHQNNInga/HixTAYDPDz80NiYiJ27txpd+w//vEP3HHHHWjRogVatGiBlJQUq/FCCMyYMQOtW7eGv78/UlJScPjwYc2Y3377DY888ghCQkIQFhaGMWPG4OLFi43y/IiIiIiIiNwefK1duxZZWVnIzs7G7t270b17d6SmpuLMmTM2x2/evBkjRozAV199hYKCAsTExGDgwIE4deqUOuaVV17B66+/jqVLl2LHjh0IDAxEamoqrly5oo555JFHsH//fnzxxRf45JNPsHXrVowfP77Rny8REREREXkmSQgh3DmBxMRE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\n",
      "text/plain": [
       "<Figure size 1000x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os\n",
    "from collections import defaultdict\n",
    "from functools import partial\n",
    "\n",
    "import numpy as np\n",
    "import pyro\n",
    "import pyro.distributions as dist\n",
    "import scipy.stats\n",
    "import torch\n",
    "import torch.distributions.constraints as constraints\n",
    "from matplotlib import pyplot\n",
    "from pyro.infer import SVI, Trace_ELBO\n",
    "from pyro.optim import Adam\n",
    "from pyro.poutine import block, replay, trace\n",
    "\n",
    "# this is for running the notebook in our testing framework\n",
    "n_steps = 2 if smoke_test else 12000\n",
    "pyro.set_rng_seed(2)\n",
    "\n",
    "# clear the param store in case we're in a REPL\n",
    "pyro.clear_param_store()\n",
    "\n",
    "# Sample observations from a Normal distribution with loc 4 and scale 0.1\n",
    "n = torch.distributions.Normal(torch.tensor([4.0]), torch.tensor([0.1]))\n",
    "data = n.sample((100,))\n",
    "\n",
    "\n",
    "def guide(data, index):\n",
    "    scale_q = pyro.param('scale_{}'.format(index), torch.tensor([1.0]), constraints.positive)\n",
    "    loc_q = pyro.param('loc_{}'.format(index), torch.tensor([0.0]))\n",
    "    pyro.sample(\"z\", dist.Normal(loc_q, scale_q))\n",
    "\n",
    "\n",
    "def model(data):\n",
    "    prior_loc = torch.tensor([0.])\n",
    "    prior_scale = torch.tensor([5.])\n",
    "    z = pyro.sample('z', dist.Normal(prior_loc, prior_scale))\n",
    "    scale = torch.tensor([0.1])\n",
    "\n",
    "    with pyro.plate('data', len(data)):\n",
    "        pyro.sample('x', dist.Normal(z*z, scale), obs=data)\n",
    "\n",
    "\n",
    "def relbo(model, guide, *args, **kwargs):\n",
    "    approximation = kwargs.pop('approximation')\n",
    "\n",
    "    # We first compute the elbo, but record a guide trace for use below.\n",
    "    traced_guide = trace(guide)\n",
    "    elbo = pyro.infer.Trace_ELBO(max_plate_nesting=1)\n",
    "    loss_fn = elbo.differentiable_loss(model, traced_guide, *args, **kwargs)\n",
    "\n",
    "    # We do not want to update parameters of previously fitted components\n",
    "    # and thus block all parameters in the approximation apart from z.\n",
    "    guide_trace = traced_guide.trace\n",
    "    replayed_approximation = trace(replay(block(approximation, expose=['z']), guide_trace))\n",
    "    approximation_trace = replayed_approximation.get_trace(*args, **kwargs)\n",
    "\n",
    "    relbo = -loss_fn - approximation_trace.log_prob_sum()\n",
    "    \n",
    "    # By convention, the negative (R)ELBO is returned.\n",
    "    return -relbo\n",
    "\n",
    "\n",
    "def approximation(data, components, weights):\n",
    "    assignment = pyro.sample('assignment', dist.Categorical(weights))\n",
    "    result = components[assignment](data)\n",
    "    return result\n",
    "\n",
    "\n",
    "def boosting_bbvi():\n",
    "    # T=2\n",
    "    n_iterations = 2\n",
    "    initial_approximation = partial(guide, index=0)\n",
    "    components = [initial_approximation]\n",
    "    weights = torch.tensor([1.])\n",
    "    wrapped_approximation = partial(approximation, components=components, weights=weights)\n",
    "\n",
    "    locs = [0]\n",
    "    scales = [0]\n",
    "\n",
    "    for t in range(1, n_iterations + 1):\n",
    "        \n",
    "        # Create guide that only takes data as argument\n",
    "        wrapped_guide = partial(guide, index=t)\n",
    "        losses = []\n",
    "\n",
    "        adam_params = {\"lr\": 0.01, \"betas\": (0.90, 0.999)}\n",
    "        optimizer = Adam(adam_params)\n",
    "\n",
    "        # Pass our custom RELBO to SVI as the loss function.\n",
    "        svi = SVI(model, wrapped_guide, optimizer, loss=relbo)\n",
    "        for step in range(n_steps):\n",
    "            # Pass the existing approximation to SVI.\n",
    "            loss = svi.step(data, approximation=wrapped_approximation)\n",
    "            losses.append(loss)\n",
    "\n",
    "            if step % 100 == 0:\n",
    "                print('.', end=' ')\n",
    "\n",
    "        # Update the list of approximation components.\n",
    "        components.append(wrapped_guide)\n",
    "        \n",
    "        # Set new mixture weight.\n",
    "        new_weight = 2 / (t + 1)\n",
    "\n",
    "        # In this specific case, we set the mixture weight of the second component to 0.5.\n",
    "        if t == 2:\n",
    "            new_weight = 0.5\n",
    "        weights = weights * (1-new_weight)\n",
    "        weights = torch.cat((weights, torch.tensor([new_weight])))\n",
    "\n",
    "        # Update the approximation\n",
    "        wrapped_approximation = partial(approximation, components=components, weights=weights)\n",
    "\n",
    "        print('Parameters of component {}:'.format(t))\n",
    "        scale = pyro.param(\"scale_{}\".format(t)).item()\n",
    "        scales.append(scale)\n",
    "        loc = pyro.param(\"loc_{}\".format(t)).item()\n",
    "        locs.append(loc)\n",
    "        print('loc = {}'.format(loc))\n",
    "        print('scale = {}'.format(scale))\n",
    "\n",
    "\n",
    "    # Plot the resulting approximation\n",
    "    X = np.arange(-10, 10, 0.1)\n",
    "    pyplot.figure(figsize=(10, 4), dpi=100).set_facecolor('white')\n",
    "    total_approximation = np.zeros(X.shape)\n",
    "    for i in range(1, n_iterations + 1):\n",
    "        Y = weights[i].item() * scipy.stats.norm.pdf((X - locs[i]) / scales[i])\n",
    "        pyplot.plot(X, Y)\n",
    "        total_approximation += Y\n",
    "    pyplot.plot(X, total_approximation)\n",
    "    pyplot.plot(data.data.numpy(), np.zeros(len(data)), 'k*')\n",
    "    pyplot.title('Approximation of posterior over z')\n",
    "    pyplot.ylabel('probability density')\n",
    "    pyplot.show()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    boosting_bbvi()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### References\n",
    "\n",
    "[1] Locatello, Francesco, et al. \"Boosting black box variational inference.\" Advances in Neural Information Processing Systems. 2018.\n",
    "\n",
    "[2] Ranganath, Rajesh, Sean Gerrish, and David Blei. \"Black box variational inference.\" Artificial Intelligence and Statistics. 2014.\n",
    "\n",
    "[3] Blei, David M., Alp Kucukelbir, and Jon D. McAuliffe. \"Variational inference: A review for statisticians.\" Journal of the American statistical Association 112.518 (2017): 859-877."
   ]
  }
 ],
 "metadata": {
  "file_extension": ".py",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  },
  "mimetype": "text/x-python",
  "name": "python",
  "npconvert_exporter": "python",
  "pygments_lexer": "ipython3",
  "version": 3
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
